package edu.cuit.avatar.common;

import edu.cuit.avatar.common.handler.ResultSetHandler;

import javax.sql.RowSet;
import javax.sql.rowset.CachedRowSet;
import javax.sql.rowset.RowSetProvider;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

/**
 * @author <a href="mailto:1020zhaodan@163.com">Adan</a>
 * @version 1.0
 * @date 2025/7/25 16:24
 */
public enum JdbcTemplate {
    TEMPLATE;

    /**
     * 封装顶层模板方法:dml操作
     * @param sql: 可变的sql语句子类通过参数传递
     * @param params: 可变的sql参数值
     *
     * @return 影响的行数
     */
    public int executeUpdate(String sql, Object...params){
        var conn = JdbcHelper.getInstance().getConnection();
        try {
            var ptst = conn.prepareStatement(sql);
            //对sql参数进行设值
            for(var i = 0; params != null && i < params.length; i++)
                ptst.setObject(i + 1, params[i]);
            return ptst.executeUpdate();
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JdbcHelper.getInstance().free(conn);
        }
    }


    /**
     * 封装顶层模板方法:插入方法，需要返回自增主键
     * @param sql: 可变的sql语句子类通过参数传递
     * @param params: 可变的sql参数值
     *
     * @return 自增主键值
     */
    public Integer insert(String sql, Object...params){
        var conn = JdbcHelper.getInstance().getConnection();
        try {
            var ptst = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
            //对sql参数进行设值
            for(var i = 0; params != null && i < params.length; i++)
                ptst.setObject(i + 1, params[i]);
            ptst.executeUpdate();
            var rs = ptst.getGeneratedKeys();
            return rs.next() ? rs.getInt(1) : null;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            JdbcHelper.getInstance().free(conn);
        }
    }

    public RowSet executeQuery(String sql, Object...params){
        var conn = JdbcHelper.getInstance().getConnection();
        try {
            var ptst = conn.prepareStatement(sql);
            //对sql参数进行设值
            for(var i = 0; params != null && i < params.length; i++)
                ptst.setObject(i + 1, params[i]);
            //将查询结果集填充到离线结果集(内存)中
            ResultSet rs = ptst.executeQuery();
            CachedRowSet rowSet = RowSetProvider.newFactory().createCachedRowSet();
            rowSet.populate(rs);
            return rowSet;
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            //Connection关闭,和其相关的(ResultSet,Statement等资源)也相继释放
            JdbcHelper.getInstance().free(conn);
        }
    }


    public<T> T executeQuery(String sql, ResultSetHandler<T> handler, Object...params){
        var conn = JdbcHelper.getInstance().getConnection();
        try {
            var ptst = conn.prepareStatement(sql);
            //对sql参数进行设值
            for(var i = 0; params != null && i < params.length; i++)
                ptst.setObject(i + 1, params[i]);
            //将查询结果集填充到离线结果集(内存)中
            ResultSet rs = ptst.executeQuery();
            return handler.process(rs);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        } finally {
            //Connection关闭,和其相关的(ResultSet,Statement等资源)也相继释放
            JdbcHelper.getInstance().free(conn);
        }
    }
}
